using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TestGame.Entities;
using XNA.Common;
using XNA.Common.Objects;

namespace TestGame
{
	/// <summary>
	/// This is the main type for your game
	/// </summary>
	public class TestGame : Game
	{
		#region CONSTRUCTION

		public TestGame()
		{
			Graphics = new GraphicsDeviceManager (this);
			Content.RootDirectory = "Content";

			// Game Objects
			GameObjects = new List<GameObject> ();

			GameObjects.Add (new World (this));
			
			var player = new Player (72, 0, 48, 16);
			GameObjects.Add (player);

			Camera = new Camera (
				player,
				new Vector2 (32, 6),
				new Vector2 (0, 0));
		}
		
		#endregion

		#region PROPERTIES

		public GraphicsDeviceManager Graphics
		{
			get;
			set;
		}

		public ICollection<GameObject> GameObjects
		{
			get;
			set;
		}

		public Camera Camera
		{
			get;
			set;
		}

		#endregion
		
		#region METHODS (PROTECTED)

		protected override void Initialize()
		{
			Window.Title = "Test Game";

			Graphics.PreferredBackBufferWidth = 640;
			Graphics.PreferredBackBufferHeight = 480;
			Graphics.IsFullScreen = false;
			Graphics.ApplyChanges ();

			PaintBrush.Brush.Initialize (GraphicsDevice);

			foreach (var gameObj in GameObjects)
			{
				gameObj.Initialize ();
			}

			base.Initialize();
		}

		/// <summary>
		/// LoadContent will be called once per game and is the place to load
		/// all of your content.
		/// </summary>
		protected override void LoadContent()
		{
			PaintBrush.Brush.LoadContent (Content);

			foreach (var gameObj in GameObjects)
			{
				gameObj.LoadContent (Content);
			}

			base.LoadContent ();
		}

		protected override void UnloadContent ()
		{
			// TODO: Unload any non ContentManager content here
		}

		/// <summary>
		/// Allows the game to run logic such as updating the world,
		/// checking for collisions, gathering input, and playing audio.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Update (GameTime gameTime)
		{
			// Allows the game to exit
			if (Keyboard.GetState ().IsKeyDown (Keys.Escape))
			{
				this.Exit ();
			}

			foreach (var gameObj in GameObjects)
			{
				gameObj.Update (gameTime);
			}

			base.Update (gameTime);
		}

		/// <summary>
		/// This is called when the game should draw itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Draw (GameTime gameTime)
		{
			GraphicsDevice.Clear (ClearOptions.Target | ClearOptions.DepthBuffer,
				Color.DarkSlateBlue, 1, 0);

			PaintBrush.Brush.ViewMatrix = Camera.CalculateViewMatrix ();

			foreach (var gameObj in GameObjects)
			{
				gameObj.Draw (gameTime);
			}
			
			base.Draw (gameTime);
		}

		#endregion

		#region METHODS (PRIVATE)

		#endregion

		#region FIELDS

		#endregion
	}
}
